#include <stdlib.h>		/* for NULL */
#include <math.h>		/* for sin, cos, atan and fabs */

#include "hoc.h"		/* for Symbol_t */
#include "symbol.h"		/* for install */
#include "code.h"		/* for Inst_t (used in y.tab.h) */
#include "y.tab.h"		/* for symbol types */
#include "math.h"		/* for Log, Log10, Exp, Sqrt and integer */

/* Constants */
static struct {
	char*	ptr_cname;
	double	dcval;
} consts[] = {
	{"PI",	  3.14159265358979323846},
	{"E",	  2.71828182845904523536},
	{"GAMMA", 0.57721566490153286060},	/* Euler */
	{"DEG",	 57.29577951308232087680},	/* Deg/Radian */
	{"PHI",	  1.61803398874989484820},	/* Golden Ratio */
	{NULL,	  0}
};

/* Built-in Functions */
static struct {
	char*	ptr_cname;
	double	(*ptr_dfunc)(double);
} builtins[] = {
	{"sin",	  sin},
	{"cos",	  cos},
	{"atan",  atan},
	{"log",	  Log},		/* Check Args */
	{"log10", Log10},	/* Check Args */
	{"exp",	  Exp},		/* Check Args */
	{"sqrt",  Sqrt},	/* Check Args */
	{"int",	  integer},	/* Check Args */
	{"abs",	  fabs},
	{NULL,	  NULL}
};

/* Keywords */
static struct {
	char*	ptr_cname;
	int		itoken;
} keywords[] = {
	{"proc",	PROC},
	{"func",	FUNC},
	{"return",	RETURN},
	{"if",		IF},
	{"else",	ELSE},
	{"while",	WHILE},
	{"print",	PRINT},
	{"read",	READ},
	{"dump",	DUMP},
	{"trace",	TRACE},
	{"all",	ALL},
	{NULL,		NULL}
};

/* Types */
static struct {
	char*	ptr_cname;
	int		itoken;
} types[] = {
	{"int",	INT},
	{"bool",	BOOL},
	{"float",	FLOAT},
	{"char",	CHAR},
	{NULL,	NULL}
};

/* Booleans */
static struct {
	char*	ptr_cname;
	int		itoken;
	bool		value;
} booleans[] = {
	{"true",	TRUE,	true},
	{"false",	FALSE,false},
	{NULL,	NULL}
};

/* Initlise Symbol Table */
void initsym() {
	int i;
	Symbol_t* ptr_sym;

	/* Install Constants */
	for ( i = 0; consts[i].ptr_cname != NULL; i++ ) {
		install( consts[i].ptr_cname, VAR, FLOAT, consts[i].dcval );
	}

	/* Install Built-in Functions */
	for ( i = 0; builtins[i].ptr_cname != NULL; i++ ) {
		ptr_sym = install( builtins[i].ptr_cname, BLTIN, NULL, 0.0 );
		ptr_sym->u.ptr_dfunc = builtins[i].ptr_dfunc;
	}

	/* Install Keywords */
	for ( i = 0; keywords[i].ptr_cname != NULL; i++ ) {
		install(keywords[i].ptr_cname, keywords[i].itoken, NULL, 0.0);
	}

	/* Install Types */
	for ( i = 0; types[i].ptr_cname != NULL; i++ ) {
		install(types[i].ptr_cname, types[i].itoken, types[i].itoken, 0.0);
	}

	/* Install Booleans */
	for ( i = 0; booleans[i].ptr_cname != NULL; i++ ) {
		install(booleans[i].ptr_cname, booleans[i].itoken, BOOLEAN, booleans[i].value);
	}
}
